<style>
	/* crbug.com/1471465 */
	dl.switch > dt {
		counter-increment: list-item 0;
	}
</style>
<pre class='metadata'>
Title: Pointer-driven Animations Module Level 1
Group: CSSWG
Status: ED
Work Status: exploring
Shortname: pointer-animations
Level: 1
Group: CSSWG
ED: https://drafts.csswg.org/pointer-animations-1/
Abstract: Defines CSS properties and an API for creating animations that are tied to
          the pointer position over a specified range. That range can be relative to the viewport
          or an element’s bounding box.
Editor: Yehonatan Daniv, Wix.com, yehonatand@wix.com w3cid 136300
Markup Shorthands: markdown yes
</pre>
<pre class=anchors>
urlPrefix: https://html.spec.whatwg.org/multipage/window-object.html; type: dfn; spec: html
	text: document associated with a window; url: concept-document-window
urlPrefix: https://drafts.csswg.org/web-animations-2/; type: dfn; spec: web-animations-2
	text: calculating an auto-aligned start time
</pre>
<pre class=link-defaults>
spec:web-animations-1;
	type:interface; text:AnimationTimeline
	type:attribute; text:currentTime
	type:dfn;
		text:current time
		text:active interval
		text:start delay
		text:end delay
		text:active duration
		text:iteration count
		text:iteration duration
		text:finished play state
		text:play state
		text:start time
		text:effective playback rate
		text:effect value
spec:html;
	type:dfn; for:/; text:browsing context
	type:method; text:requestAnimationFrame()
spec: cssom-view-1; type: dfn;
	text: overflow direction;
	text: css layout box
spec:css-writing-modes-4; type: dfn;
	text:start
	text:end
spec:infra; type:dfn; text:user agent
spec:selectors-4; type:dfn; text:selector
</pre>

# Introduction # {#intro}

	This specification defines mechanisms for
	driving the progress of an animation
	based on the pointer position’s progress over a specified range.
	These <dfn export>pointer-driven animations</dfn>
	use a timeline based on the pointer position,
	and are based on length, rather than time. In this way
	they operate similarly to, and share similar concepts
	with [=scroll-driven animations=].
	This module provides both an imperative API building on the
	Web Animations API as well as a declarative API building
	on CSS Animations. [[!CSS-ANIMATIONS-2]] [[!WEB-ANIMATIONS-1]]

## Relationship to other specifications ## {#other-specs}

	Web Animations [[WEB-ANIMATIONS-1]] defines
	an abstract conceptual model for animations on the Web platform,
	with elements of the model including [=animations=] and their [=timelines=],
	and associated programming interfaces.
	This specification extends the Web Animations model
	by defining [=pointer progress timelines=]
	and allowing them to drive progress in [=animations=]
	to create [=pointer-driven animations=].

	This specification introduces both
	programming interfaces for interacting with these concepts,
	as well as CSS properties that apply these concepts
	to CSS Animations [[CSS-ANIMATIONS-1]].
	To the extent the behavior of these CSS properties is described
	in terms of the programming interfaces,
	[=User agents=] that do not support scripting
	may still conform to this specification
	by implementing the CSS features to behave
	as if the underlying programming interfaces were in place.

	This specification was derived from, and inspired by the
	concepts and features introduced in the Scroll-Driven
	Animations module [[!SCROLL-ANIMATIONS-1]] for specifying
	progress-based timelines and animations.

	Like most operations in CSS besides [=selector=] matching,
	features in this specification operate over
	the [=flattened element tree=].

## Value Definitions ## {#values}

	This specification follows the
	<a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a>
	from [[!CSS2]]
	using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a>
	from [[!CSS-VALUES-3]].
	Value types not defined in this specification
	are defined in CSS Values &amp; Units [[!CSS-VALUES-3]].
	Combination with other CSS modules may expand the definitions of these value types.

	In addition to the property-specific values listed in their definitions,
	all properties defined in this specification
	also accept the <a>CSS-wide keywords</a> as their property value.
	For readability they have not been repeated explicitly.

# Pointer Progress Timelines # {#pointer-timelines}

	<dfn export>Pointer progress timelines</dfn>
	are timelines linked to progress
	in the pointer position over an element’s [=principal box=]
	along a particular axis.

	The <dfn export>pointer range</dfn> is the size of the
	element’s [=principal box=] along the axis of the [=pointer progress timeline=].

	The <dfn export>pointer offset</dfn> is the position of the pointer
	relative to the start of the element’s [=pointer range=],
	as defined by {{MouseEvent/offsetX}} and {{MouseEvent/offsetY}} in [[!CSSOM-VIEW-1]].
	The startmost [=pointer offset=] represents 0% progress
	and the endmost [=pointer offset=] represents 100% progress.

	[=Pointer progress timelines=] can be referenced in 'animation-timeline'
	anonymously using the ''pointer()'' [=functional notation=]
	or by name (see [[scroll-animations-1#timeline-scoping]])
	after declaring them using the 'pointer-timeline' properties.
	In the Web Animations API,
	they can be represented anonymously by a {{PointerTimeline}} object.

## Pointer Progress Timeline Ranges ## {#pointer-timelines-ranges}

	[=pointer progress timelines=] define the following [=named timeline ranges=]:

	<dl dfn-for="animation-timeline-range" dfn-type="value">
		<dt><dfn>fill</dfn>
		<dd>
			Represents the full range of the [=pointer progress timeline=]:
			* 0% progress represents the pointer position over
				the [=start=] [=padding edge=] of the element’s [=principal box=].
			* 100% progress represents the pointer position over
				the [=end=] [=padding edge=] of the element’s [=principal box=].

		<dt><dfn>fit</dfn>
		<dd>
			Represents a range that is the same size as ''animation-timeline-range/fill'',
			but its points of 0% and 100% progress are offset according to the value of
			'animation-range-center' property, so that the point of 50% progress
			remains at the center of the range.

		<dt><dfn>cover</dfn>
		<dd>
			Represents the largest possible range of the [=pointer progress timeline=]
			that fully covers the element’s [=principal box=] according to the value of
			'animation-range-center' property as follows:
			* If the distance between the point of 50% progress and the element’s
				[=start=] [=padding edge=] is greater than the distance between the
				point of 50% progress and the element’s [=end=] [=padding edge=],
				then the 0% progress point is at the element’s [=start=] [=padding edge=],
				and the 100% progress point is at the same distance from the 50% progress
				point on the opposite side.
			* Otherwise, the 100% progress point is at the element’s [=end=]
				[=padding edge=], and the 0% progress point is at the same distance
				from the 50% progress point on the opposite side.

		<dt><dfn>contain</dfn>
		<dd>
			Represents the largest possible range that is fully contained within
			the element’s [=principal box=] according to the value of
			'animation-range-center' property as follows:
			* If the distance between the point of 50% progress and the element’s
				[=start=] [=padding edge=] is smaller than the distance between the
				point of 50% progress and the element’s [=end=] [=padding edge=],
				then the 0% progress point is at the element’s [=start=] [=padding edge=],
				and the 100% progress point is at the same distance from the 50% progress
				point on the opposite side.
			* Otherwise, the 100% progress point is at the element’s [=end=]
				[=padding edge=], and the 0% progress point is at the same distance
				from the 50% progress point on the opposite side.
	</dl>

	ISSUE: Insert diagrams.

	In all cases, the [=writing mode=] used to resolve the [=start=] and [=end=] sides
	is the [=writing mode=] of the relevant [=principal box=].
	<a href="http://www.w3.org/TR/css-transforms/">Transforms</a> are ignored,
	but [=relative positioning|relative=] and [=absolute positioning|absolute=] positioning
	are accounted for.

	[[CSS-POSITION-3]] [[CSS-TRANSFORMS-1]]

## Calculating Progress for a Pointer Progress Timeline ## {#pointer-timeline-progress}

	Progress (the [=timeline/current time=]) for a [=pointer progress timeline=]
	is calculated as:
	<var ignore=''>[=pointer offset=]</var> &div;
	<var ignore=''>[=pointer range=]</var>

	If the 0% position and 100% position coincide
	(i.e. the denominator in the [=timeline/current time=] formula is zero),
	the timeline is [=inactive timeline|inactive=].

## Anonymous Pointer Progress Timelines ## {#pointer-timelines-anonymous}

### The ''pointer()'' notation ### {#pointer-notation}

	The <dfn>pointer()</dfn> functional notation
	can be used as a <<single-animation-timeline>> value in 'animation-timeline'
	and specifies a [=pointer progress timeline=].
	Its syntax is

	<pre class="prod">
		<<pointer()>> = pointer( [ <<source>> || <<axis>> ]? )
		<dfn noexport><<axis>></dfn> = block | inline | x | y
		<dfn noexport><<source>></dfn> = root | nearest | self
	</pre>

	By default,
	''pointer()'' references the [=inline axis=] of the element’s own [=pointer range=].
	Its arguments modify this lookup as follows:

	<dl dfn-type=value dfn-for="pointer(),pointer-timeline-axis">
		<dt><dfn>block</dfn>
		<dd>
			Specifies to use the measure of progress along the
			[=block axis=] of the [=pointer range=].

		<dt><dfn>inline</dfn>
		<dd>
			Specifies to use the measure of progress along the
			[=inline axis=] of the [=pointer range=].
			(Default.)

		<dt><dfn>x</dfn>
		<dd>
			Specifies to use the measure of progress along the
			[=horizontal axis=] of the [=pointer range=].

		<dt><dfn>y</dfn>
		<dd>
			Specifies to use the measure of progress along the
			[=vertical axis=] of the [=pointer range=].

		<dt><dfn>self</dfn>
		<dd>
			Specifies to use the element’s own [=principal box=] as the [=pointer range=].
			(Default.)

		<dt><dfn>nearest</dfn>
		<dd>
			Specifies to use the nearest element’s [=parent box=] as the [=pointer range=].

		<dt><dfn>root</dfn>
		<dd>
			Specifies to use the root element’s [=principal box=] as the [=pointer range=].
	</dl>

	Each use of ''pointer()'' corresponds to its own instance of {{PointerTimeline}}
	in the Web Animations API,
	even if multiple elements use ''pointer()'' to refer
	to the same [=pointer range=] with the same arguments.

### The {{PointerTimeline}} Interface ### {#pointertimeline-interface}

	<pre class="idl">
		enum PointerAxis {
		  "block",
		  "inline",
		  "x",
		  "y"
		};

		dictionary PointerTimelineOptions {
		  Element? source;
		  PointerAxis axis = "block";
		};

		[Exposed=Window]
		interface PointerTimeline : AnimationTimeline {
		  constructor(optional PointerTimelineOptions options = {});
		  readonly attribute Element? source;
		  readonly attribute PointerAxis axis;
		};
	</pre>

	A {{PointerTimeline}} is an {{AnimationTimeline}}
	that represents a [=pointer progress timeline=].
	It can be passed to
	the {{Animation}} constructor or the {{Animatable/animate()}} method
	to link the animation to a [=pointer progress timeline=].

	<dl class="attributes" dfn-type=attribute dfn-for=PointerTimeline>
		:   <dfn>source</dfn>
		::  The element whose [=pointer offset=] drives
			the progress of the timeline.

		:   <dfn>axis</dfn>
		::  The axis that drives the progress of the timeline.
			See value definitions for <<axis>>, above.
	</dl>

	Inherited attributes:
	<dl>
		:   {{AnimationTimeline/currentTime}} (inherited from {{AnimationTimeline}})
		::  Represents the pointer progress of the [=pointer range=]
			as a percentage CSSUnitValue,
			with 0% representing its startmost [=pointer offset=].
			Null when the timeline is [=inactive timeline|inactive=].
	</dl>

	<dl class="constructors">
		:   <dfn constructor for=PointerTimeline lt="PointerTimeline(options)">PointerTimeline(options)</dfn>
		::  Creates a new {{PointerTimeline}} object using the following procedure:

			1.  Let |timeline| be the new {{PointerTimeline}} object.

			1.  Set the {{PointerTimeline/source}} of |timeline| to:

				<dl class="switch">
					:   If the `source` member of |options| is present,
					::  The `source` member of |options|.

					:   Otherwise,
					::  The [=root element=].
				</dl>

			1.  Set the {{PointerTimeline/axis}} property of |timeline|
				to the corresponding value from |options|.
	</dl>

	If the {{PointerTimeline/source}} of a {{PointerTimeline}}
	is an element whose [=principal box=] does not exist
	then the {{PointerTimeline}} is [=inactive timeline|inactive=].

	The values of {{PointerTimeline/source}} and {{AnimationTimeline/currentTime}}
	are both computed when either is requested or updated.

## Named Pointer Progress Timelines ## {#pointer-timelines-named}

	[=Pointer progress timelines=] can also be defined declaratively
	and then referenced by name
	by elements within the name’s scope
	(see [[scroll-animations-1#timeline-scoping]]).

	Such <dfn>named pointer progress timelines</dfn>
	are declared in the [=coordinated value list=]
	constructed from the 'pointer-timeline-*' properties,
	which form a [=coordinating list property group=]
	with 'pointer-timeline-name' as the [=coordinating list base property=].
	See [[css-values-4#linked-properties]].

### Naming a Pointer Progress Timeline: the 'pointer-timeline-name' property ### {#pointer-timeline-name}

	<pre class='propdef'>
	Name: pointer-timeline-name
	Value: [ none | <<dashed-ident>> ]#
	Initial: none
	Applies to: all elements
	Inherited: no
	Computed value: the keyword ''pointer-timeline-name/none'' or a list of [=CSS identifiers=]
	Animation type: not animatable
	</pre>

	Specifies names for the [=named pointer progress timelines=]
	associated with this element.

### Axis of a Pointer Progress Timeline: the 'pointer-timeline-axis' property ### {#pointer-timeline-axis}

	<pre class='propdef'>
	Name: pointer-timeline-axis
	Value: [ block | inline | x | y ]#
	Initial: block
	Applies to: all elements
	Inherited: no
	Computed value: a list of the keywords specified
	Animation type: not animatable
	</pre>

	Specifies the axis of any [=named pointer progress timelines=]
	derived from this element’s [=principal box=].
	If this element’s [=principal box=] does not exist,
	then the corresponding [=named pointer progress timeline=]
	is [=inactive timeline|inactive=].

	Values are as defined for ''pointer()''.

### Pointer Timeline Shorthand: the 'pointer-timeline' shorthand ### {#pointer-timeline-shorthand}

	<pre class='propdef shorthand'>
	Name: pointer-timeline
	Value: [ <<'pointer-timeline-name'>> <<'pointer-timeline-axis'>>? ]#
	Applies to: all elements
	</pre>

	This property is a [=shorthand=] for setting
	'pointer-timeline-name' and 'pointer-timeline-axis'
	in a single declaration.

# Privacy Considerations # {#privacy-considerations}

	There are no known privacy impacts of the features in this specification.

# Security Considerations # {#security-considerations}

	There are no known security impacts of the features in this specification.

# Appendix A: Animation Range Centering # {#animation-range-centering}

	ISSUE: This section should move to CSS-ANIMATIONS-2 and WEB-ANIMATIONS-2.

	The section [[scroll-animations-1#named-range-animation-declaration]]
	introduces the concept of attaching a set of animation keyframes
	to an [=animation attachment range=], which creates a single linear
	range of progress for the animation.

	Pointer-driven animations adds a new ability,
	to set the focal point - the point of 50% progress -
	of the animation to a specific point, rather than the
	default center of the [=animation attachment range=], which can be done
	using the 'animation-range-center' property.

	The <dfn>animation range center subject</dfn> is the element whose
	[=principal box=] is the range relative to which
	the center of the active range is calculated, and is represented
	by the <dfn><<timeline-range-center-subject>></dfn> value type,
	which indicates a [=CSS identifier=] representing
	one of the following:

	<dl dfn-type=value dfn-for="timeline-range-center-subject">
		<dt><dfn>source</dfn>
		<dd>
			The element whose [=pointer offset=]
			drives the progress of the timeline.

		<dt><dfn>target</dfn>
		<dd>
			The element to which the animation is applied.
	</dl>

	The point of 50% progress can be smaller than the 0% progress point
	or larger than the 100% progress point. In such cases, the
	[=animation attachment range=] is cut off at the 50% progress point.

## Specifying an Animation’s Timeline Range Center: the 'animation-range-center' property ## {#animation-range-center}

	<pre class="propdef">
		Name: animation-range-center
		Value: [ normal | [ <<length-percentage>> | <<timeline-range-center-subject>> <<length-percentage>>? ] ]#
		Initial: normal
		Applies to: all elements
		Inherited: no
		Percentages: relative to the corresponding dimension of the specified timeline range center subject, else
			relative to the start of the [=animation attachment range=]
		Computed value: list, each item either the keyword ''animation-range-center/normal''
			or a timeline range center subject and a length-percentage value
		Animation type: not animatable
	</pre>

	Specifies the center point of the [=animation attachment range|animations’s attachment range=],
	i.e. where the 50% progress point of the animations’s range is.

	Values have the following meanings:

	<dl dfn-for="animation-range-center" dfn-type=value>
		<dt><dfn>normal</dfn>
		<dd>
			The 50% progress point of the animation’s [=active interval=]
			is at the center of the [=animation attachment range=].

		<dt><dfn><<length-percentage>></dfn>
		<dd>
			The 50% progress point of the animation’s [=active interval=]
			is at the specified point on the [=timeline=]
			measuring from the start of the [=animation attachment range=].
			Percentages are relative to the size of the [=animation attachment range=].

		<dt><dfn><<timeline-range-name>> <<length-percentage>>?</dfn>
		<dd>
			The 50% progress point of the animation’s [=active interval=]
			is at the specified point relative to the [=start=] [=padding edge=] of
			the specified [=animation range center subject=]’s [=principal box=].
			If the <<length-percentage>> is omitted,
			it defaults to 50%.
	</dl>